﻿#include "AF_Graphics.h"
#include "AF_Platform.h"

namespace AF
{
	NotRender Graphics::m_NothingRender;

	UINT Graphics::m_nID = 0;
	UINT Graphics::GetID()
	{
		return m_nID++;
	}

	Graphics::Graphics() :
		ATTRIB(Visible)(true),
		ATTRIB(Location)(AF_POINT_ORIGIN),
		ATTRIB(Through)(THROUGH_NONE),
		ATTRIB(Size)(AF_SIZE_ZERO),
		ATTRIB(Anchor)(0),
		ATTRIB(AnchorOffset)(AF_POINT_ORIGIN),
		ATTRIB(Alpha)(255),
		ATTRIB(Angle)(AF_ANGLE_DEFAULT),
		ATTRIB(Zoom)(AF_ZOOM_DEFAULT),
		m_pRender(&m_NothingRender),
		m_pgGroup(NULL),
		m_isIgnoreSize(false)
	{
		m_nGType = GRAPHICS_UNKNOW;

		static char _szGraphicsName[20];
		_MEMSET(_szGraphicsName, 0, sizeof(_szGraphicsName));
		_SPRINTF(_szGraphicsName, "G_%d", GetID());
		ATTRIB(GraphicsName) = _szGraphicsName;
	}

	Graphics::~Graphics()
	{
		int nActs = m_tabPActions.GetCount();
		if(nActs > 0)
		{
			ActionNode** pActs = AF_NEW_ARY(ActionNode*, nActs);
			m_tabPActions.Clean(pActs);
			for(int i = 0; i < nActs; i++)
			{
				if(pActs[i]->isCreate)
				{
					AF_DELETE(pActs[i]->pAction);
				}
				AF_DELETE(pActs[i]);
			}
			AF_DELETE(pActs);
		}
	}

	bool Graphics::OnPreRender(Graphics* pGraphics)
	{
		if(m_pgGroup != NULL)
			return m_pgGroup->OnPreRender(this);

		return true;
	}

	void Graphics::SetGraphicsName(_STRING strGraphicsName)
	{
		if(ATTRIB(GraphicsName).substr(0, 2) == "G_")
			ATTRIB(GraphicsName) = strGraphicsName;
	}

	void Graphics::SetHide(bool isHide)
	{
		ATTRIB(Visible) = !isHide;
	}

	void Graphics::SetLocation(int nX, int nY)
	{
		ATTRIB(Location).Set(nX, nY);
	}

	void Graphics::SetLocation(float fX, float fY, Graphics* pgFrame)
	{
		int nWidth = 0;
		int nHeight = 0;

		if(pgFrame != NULL)
		{
			nWidth = pgFrame->GetSize().nWidth;
			nHeight = pgFrame->GetSize().nHeight;
		}
		else if(m_pgGroup != NULL)
		{
			nWidth = m_pgGroup->GetSize().nWidth;
			nHeight = m_pgGroup->GetSize().nHeight;
		}
		else
		{
// 			nWidth = THE_PLATFORM->GetScreenWidth();
// 			nHeight = THE_PLATFORM->GetScreenHeight();
		}

		ATTRIB(Location).Set((int)(nWidth * fX), (int)(nHeight * fY));
	}

	void Graphics::SetAnchor(int nX, int nY)
	{
		ATTRIB(Anchor) = 0;
		SetAnchorOffset(nX, nY);
	}

	void Graphics::SetAnchor(float fX, float fY)
	{
		ATTRIB(Anchor) = 0;
		SetAnchorOffset((int)(ATTRIB(Size).nWidth * fX), (int)(ATTRIB(Size).nHeight * fY));
	}

	void Graphics::SetAnchorOffset(int nX, int nY)
	{
		ATTRIB(AnchorOffset).nX = nX;
		ATTRIB(AnchorOffset).nY = nY;
	}

	void Graphics::SetSize(unsigned int nWidth, unsigned int nHeight)
	{
		ATTRIB(Size).nWidth = nWidth;
		ATTRIB(Size).nHeight = nHeight;
	}

	void Graphics::SetRender(Renderable* pRender)
	{
		m_pRender = pRender;
	}

	bool Graphics::GetScreenVisible()
	{
		if(ATTRIB(Visible) && m_pgGroup != NULL)
			return m_pgGroup->GetScreenVisible();
		else
			return ATTRIB(Visible);
	}

	int Graphics::GetScreenPosX()
	{
		int _nGroupX;
		double _dGroupZoom;
		_nGroupX = 0;
		_dGroupZoom = 1.0f;

		if(m_pgGroup != NULL)
		{
			_dGroupZoom = m_pgGroup->GetScreenZoom();

			_nGroupX = m_pgGroup->GetScreenPosX();
			_nGroupX += m_pgGroup->GetAnchorOffset().nX;

			if((m_pgGroup->GetAnchor() & ANCHOR_HMARK) == ANCHOR_LEFT) {}
			else if((m_pgGroup->GetAnchor() & ANCHOR_HMARK) == ANCHOR_HCENTER)
				_nGroupX -= m_pgGroup->GetScreenSizeW() >> 1;
			else if((m_pgGroup->GetAnchor() & ANCHOR_HMARK) == ANCHOR_RIGHT)
				_nGroupX -= m_pgGroup->GetScreenSizeW();
		}

		return (int)(ATTRIB(Location).nX * _dGroupZoom) + _nGroupX;
	}

	int Graphics::GetScreenPosY()
	{
		int _nGroupY;
		double _dGroupZoom;
		_nGroupY = 0;
		_dGroupZoom = 1.0f;

		if(m_pgGroup != NULL)
		{
			_dGroupZoom = m_pgGroup->GetScreenZoom();

			_nGroupY = m_pgGroup->GetScreenPosY();
			_nGroupY += m_pgGroup->GetAnchorOffset().nY;

			if((m_pgGroup->GetAnchor() & ANCHOR_VMARK) == ANCHOR_TOP) {}
			else if((m_pgGroup->GetAnchor() & ANCHOR_VMARK) == ANCHOR_VCENTER)
				_nGroupY -= m_pgGroup->GetScreenSizeH() >> 1;
			else if((m_pgGroup->GetAnchor() & ANCHOR_VMARK) == ANCHOR_BUTTON)
				_nGroupY -= m_pgGroup->GetScreenSizeH();
		}

		return (int)(ATTRIB(Location).nY * _dGroupZoom) + _nGroupY; 
	}

	int Graphics::GetScreenSizeW()
	{
		return (int)((double)(GetSize().nWidth) * GetScreenZoom());
	}
	
	int Graphics::GetScreenSizeH()
	{
		return (int)((double)(GetSize().nHeight) * GetScreenZoom());
	}

	ThroughType Graphics::GetScreenThrough()
	{
		if(GetThrough() != THROUGH_BOTH && m_pgGroup != NULL)
		{
			if(GetThrough() == THROUGH_NONE)
				return m_pgGroup->GetScreenThrough();

			else if(m_pgGroup->GetScreenThrough() == THROUGH_NONE)
				return GetThrough();

			else if(GetThrough() != m_pgGroup->GetScreenThrough())
				return THROUGH_BOTH;

			else
				return GetThrough();
		}
		else
			return GetThrough();
	}


	BYTE Graphics::GetScreenAlpha()
	{
		static BYTE bAlpha;
		if(GetAlpha() > 0 && m_pgGroup != NULL)
		{
			bAlpha = m_pgGroup->GetScreenAlpha();
			if(bAlpha == 255)
				return GetAlpha();
			else
				return (BYTE)((GetAlpha() * bAlpha) >> 8);
		}
		else
			return GetAlpha();
	}

	double Graphics::GetScreenAngle()
	{
		if(m_pgGroup != NULL)
			return GetAngle() + m_pgGroup->GetScreenAngle();
		else
			return GetAngle();
	}

	double Graphics::GetScreenZoom()
	{
		if(m_pgGroup != NULL)
			return GetZoom() * m_pgGroup->GetScreenZoom();
		else
			return GetZoom();
	}

	Bundle& Graphics::Information()
	{
		return m_Information;
	}

	int Graphics::GetGType()
	{
		return m_nGType;
	}

	bool Graphics::GetHide()
	{
		return !GetVisible();
	}

	void Graphics::DockGroup(Graphics* pgGroup)
	{
		if(pgGroup != NULL && m_pgGroup != NULL)
		{
			((Face*)m_pgGroup)->RemoveGraphics(this);
		}

		m_pgGroup = pgGroup;
	}

	Graphics* Graphics::GetDockGroup()
	{
		return m_pgGroup;
	}

	void Graphics::IgnoreSize()
	{
		m_isIgnoreSize = true;
	}

	bool Graphics::IsIgnoreSize()
	{
		return m_isIgnoreSize;
	}

	bool Graphics::AddAction(_STRING strActionName, Action* pAction)
	{
		AF_CHECK_R(strActionName != "", false);
		AF_CHECK_R(pAction != NULL, false);

		if(m_tabPActions.Find(strActionName) >= 0)
		{
			AF_ERRMARK();
			return false;
		}

		ActionNode* _pANode = AF_NEW(ActionNode);
		_pANode->isCreate = false;
		_pANode->pAction = pAction;
		m_tabPActions.Put(strActionName, _pANode);

		pAction->SetHostGraphics(this);

		return true;
	}

	Action* Graphics::RemoveAction(_STRING strActionName)
	{
		if(m_tabPActions.Find(strActionName) < 0)
		{
			AF_ERRMARK();
			return NULL;
		}

		ActionNode* _pANode = m_tabPActions.Get(strActionName);
		m_tabPActions.Remove(strActionName);

		Action* _pRemoveAct = _pANode->pAction;
		AF_DELETE(_pANode);

		return _pRemoveAct;
	}

	Action* Graphics::GetAction(_STRING strActionName)
	{
		if(m_tabPActions.Find(strActionName) < 0)
		{
			AF_ERRMARK();
			return NULL;
		}

		return m_tabPActions.Get(strActionName)->pAction;
	}

	void Graphics::PlayAction(_STRING strActionName)
	{
		if(m_tabPActions.Find(strActionName) < 0)
		{
			AF_ERRMARK();
			return;
		}

		m_tabPActions.Get(strActionName)->pAction->Play();
	}

	void Graphics::PauseAction(_STRING strActionName)
	{
		if(m_tabPActions.Find(strActionName) < 0)
		{
			AF_ERRMARK();
			return;
		}

		m_tabPActions.Get(strActionName)->pAction->Pause();
	}

	void Graphics::StopAction(_STRING strActionName)
	{
		if(m_tabPActions.Find(strActionName) < 0)
		{
			AF_ERRMARK();
			return;
		}

		m_tabPActions.Get(strActionName)->pAction->Stop();
	}

}